#include "stdafx.h"
#include "EntityLua.h"
#include "EntityDefinition.h"
#include "Combat/CombatSysIf.h"
#include "Combat/CombatLua.h"
#include "Scene/SceneLua.h"

namespace EntityLua
{

bool push(lua_State* L, IEntity* pEntity)
{
	IEntity** pp = (IEntity**)lua_newuserdata(L, sizeof(IEntity*));
	*pp = pEntity;
	luaL_getmetatable(L, "woe.entity");
	if (lua_istable(L, -1))
	{
		lua_setmetatable(L, -2);
		return true;
	}
	else
	{
		LOG_ERROR("Failed to push IEntity to lua, metatable not found!");
		return false;
	}
}

IEntity* getUserData(lua_State* L)
{
	IEntity**pp = (IEntity**)luaL_checkudata(L, 1, "woe.entity");
	if (pp==NULL)
	{
		return NULL;
	}
	else
	{
		return *pp;
	}
}

int dump(lua_State* L)
{
	
	IEntity* pEntity = getUserData(L);

	if (pEntity)
	{
		std::cout<<"---------------------------------------"<<std::endl;
		std::cout<<"Name: "<<pEntity->getName()<<"  lvl: "<<pEntity->getLevel()<<"  hid: "<<pEntity->getStaticID()<<std::endl;
		ICombatSys* pCombat = pEntity->getCombatSys();
		if (pCombat)
		{
			std::cout<<"hp: "<<pCombat->getHP()<<"/"<<pCombat->getMaxHP()<<"  mp: "<<pCombat->getMP()<<"/"<<pCombat->getMaxHP()<<std::endl;
			std::cout<<"vit: "<<pCombat->getProps(prop_vit)<<" str: "<<pCombat->getProps(prop_str)<<" agi: "<<pCombat->getProps(prop_agi)<<" int: "<<pCombat->getProps(prop_int)<<std::endl;
			std::cout<<"tohit: "<<pCombat->getProps(prop_tohit)<<" tododge: "<<pCombat->getProps(prop_tododge)<<std::endl;
			std::cout<<"c:  "<<pCombat->getProps(prop_critical)<<" t: "<<pCombat->getProps(prop_resist)<<std::endl;
			std::cout<<"ap: "<<pCombat->getProps(prop_ap)<<" dp:  "<<pCombat->getProps(prop_dp)<<std::endl;
		}
	}
	return 0;
}

int getCombatSys(lua_State* L)
{
	IEntity* pEntity = getUserData(L);

	if (pEntity)
	{
		ICombatSys* pCombat = pEntity->getCombatSys();
		if (pCombat)
		{
			CombatLua::push(L, pCombat);
			return 1;
		}
	}
	return 0;
}

int getScene(lua_State* L)
{
	IEntity* pEntity = getUserData(L);

	if (pEntity)
	{
		IScene* pScene = pEntity->getScene();
		if (pScene)
		{
			SceneLua::push(L, pScene);
			return 1;
		}
	}
	return 0;
}

int getStaticID(lua_State* L)
{
	IEntity* pEntity = getUserData(L);

	if (pEntity)
	{
		lua_pushinteger(L, pEntity->getStaticID());
	}
	else
	{
		lua_pushinteger(L, 0);
	}
	return 1;
}


int setName(lua_State* L)
{
	IEntity* pEntity = getUserData(L);
	if (pEntity)
	{
		pEntity->setName(lua_tostring(L, 2));
	}
	return 0;
}

int getName(lua_State* L)
{
	IEntity* pEntity = getUserData(L);
	if (pEntity)
	{
		lua_pushstring(L, pEntity->getName().c_str());
	}
	else
	{
		lua_pushstring(L, "NoName");
	}
	return 1;
}

int getType(lua_State* L)
{
	IEntity* pEntity = getUserData(L);

	if (pEntity)
	{
		lua_pushinteger(L, pEntity->getType());
	}
	return 1;
}

int isM(lua_State* L)
{
	IEntity* pEntity = getUserData(L);
	if (pEntity)
	{
		lua_pushboolean(L, pEntity->getType()==Entity::ett_Monster);
	}
	return 1;
}

int isP(lua_State* L)
{
	IEntity* pEntity = getUserData(L);
	if (pEntity)
	{
		lua_pushboolean(L, pEntity->getType()==Entity::ett_Player);
	}
	return 1;
}

int isR(lua_State* L)
{
	IEntity* pEntity = getUserData(L);
	if (pEntity)
	{
		lua_pushboolean(L, pEntity->getType()==Entity::ett_Role || pEntity->getType()==Entity::ett_Player);
	}
	return 1;
}

int isN(lua_State* L)
{
	IEntity* pEntity = getUserData(L);
	if (pEntity)
	{
		lua_pushboolean(L, pEntity->getType()==Entity::ett_NPC);
	}
	return 1;
}

int setFaction(lua_State* L)
{
	IEntity* pEntity = getUserData(L);
	if (pEntity)
	{
		pEntity->setFaction(lua_tointeger(L, 2));
	}
	return 0;
}

int getFaction(lua_State* L)
{
	IEntity* pEntity = getUserData(L);
	if (pEntity)
	{
		lua_pushinteger(L, pEntity->getFaction());
	}
	return 1;
}

int setPosition(lua_State* L)
{
	IEntity* pEntity = getUserData(L);
	if (pEntity)
	{
		int x = luaL_checkint(L, 2);
		int y = luaL_checkint(L, 3);
		int z = luaL_checkint(L, 4);

		pEntity->setPosition(x, y, z);
	}
	return 0;
}

int getPosition(lua_State* L)
{
	IEntity* pEntity = getUserData(L);
	if (pEntity)
	{
		int x = 0, y = 0, z = 0;

		pEntity->getPosition(x, y, z);

		lua_pushinteger(L, x);
		lua_pushinteger(L, y);
		lua_pushinteger(L, z);
		return 3;
	}
	return 0;
}

int setLevel(lua_State* L)
{
	IEntity* pEntity = getUserData(L);
	if (pEntity)
	{
		pEntity->setLevel(lua_tointeger(L, 2));
	}
	return 0;
}

int getLevel(lua_State* L)
{
	IEntity* pEntity = getUserData(L);
	if (pEntity)
	{
		lua_pushinteger(L, pEntity->getLevel());
	}
	else
	{
		lua_pushinteger(L, 0);
	}
	return 1;
}

int setProps(lua_State* L)
{
	IEntity* pEntity = getUserData(L);
	if (pEntity)
	{
		short idx = lua_tointeger(L, 2);
		int val = lua_tointeger(L, 3);
		pEntity->setProps(idx, val);
	}
	return 0;
}

int getProps(lua_State* L)
{
	IEntity* pEntity = getUserData(L);
	if (pEntity)
	{
		short idx = lua_tointeger(L, 2);
		lua_pushinteger(L, pEntity->getProps(idx, 0));
	}
	return 1;
}

static const luaL_Reg entity_funcs[] = {
	{"dump", dump},
	{"isM", isM},
	{"isP", isP},
	{"isR", isR},
	{"isN", isN},
	{"getStaticID", getStaticID},
	{"setName", setName},
	{"getName", getName},
	{"getCombatSys", getCombatSys},
	{"setPosition", setPosition},
	{"getPosition", getPosition},
	{"setFaction", setFaction},
	{"getFaction", getFaction},
	{"setLevel", setLevel},
	{"getLevel", getLevel},
	{"setProps", setProps},
	{"getProps", getProps},
	{NULL, NULL}
};


int libaray(lua_State* L)
{
	luaL_newmetatable(L, "woe.entity");
	// fill member list into metatable
	luaL_register(L, NULL, entity_funcs);

	// metatable.__index = metatable
	lua_pushstring(L, "__index");
	lua_pushvalue(L, -2);
	lua_settable(L, -3);

	return 0;
}

}
